package com.training1.core.tree.misc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TreeLayout {
	private int wellIndex;
	// sort by time/
	private TreeNodeDto[] nodes;

	public TreeLayout(TreeNodeDto[] tnodes) {
		int empty = 0;
		for (int i = 0; i < TreeLayoutDefinition.TREE_SIZE; i++) {
			if (tnodes[i] == null) {
				empty++;
			}
		}
		int size = TreeLayoutDefinition.TREE_SIZE - empty;
		this.nodes = new TreeNodeDto[size];
		System.arraycopy(tnodes, 0, this.nodes, 0, size);
		
		if (nodes == null || nodes.length >= 40) {
			throw new java.lang.IllegalArgumentException("outofboundary of the tree, max capacity : 39");
		}
	}

	public int getWellIndex() {
		return wellIndex;
	}

	public void setWellIndex(int wellIndex) {
		this.wellIndex = wellIndex;
	}

	public void buildTreeView() {
		int length = nodes.length;
		for (int i = 0; i < length; i++) {
			int viewIndex = TreeLayoutDefinition.findViewIndex(i);
			nodes[i].setViewIndex(viewIndex);
			nodes[i].setWellIndex(wellIndex);
			nodes[i].setLevel(TreeLayoutDefinition.getLevelIndex(viewIndex));
		}
	}
	
	public TreeNodeDto getParentNode (int viewIndex) {
		int pViewIndex = TreeLayoutDefinition.findParentViewIndex(viewIndex);
		TreeNodeDto dto = null;
		for (int i = 0; i < nodes.length; i++) {
			if (nodes[i].getViewIndex() == pViewIndex) {
				dto = nodes[i];
			}
		}
		return dto;
	}
	
	public int getTreeHeight() {
		int ncount = nodes.length;
		if(ncount == 1) {
			return 1;
		}
		else if(ncount <= 4) {
			return 2;
		}
		else if(ncount <= 13) {
			return 3;
		}
		else {
			return 4;
		}
	}

	public TreeNodeDto getRoot() {
		return this.nodes[0];
	}
	
	public List<TreeNodeDto> getAllNodes() {
		return Arrays.asList(this.nodes);
	}
	
	/**
	 * 检查该层是否已经排满, 从0 开始
	 * @param levelIndex
	 * @return true-已经满
	 */
	public boolean isLevelFull(int levelIndex) {
		int count = nodes.length;
		if(levelIndex == 0) {
			return (count > 0);
		}
		else if(levelIndex == 1) {
			return (count > 3);
		}
		else if(levelIndex == 2) {
			return (count > 12);
		}
		else {
			return false;			
		}
	}

	public List<TreeNodeDto> getLevel1() {
		if (nodes.length > 3) {
			return Arrays.asList(new TreeNodeDto[] { nodes[1], nodes[2], nodes[3] });
		} else {
			return null;
		}
	}

	public List<TreeNodeDto> getLevel2() {
		if (nodes.length > 12) {
			return Arrays.asList(new TreeNodeDto[] { nodes[4], nodes[5], nodes[6], nodes[7], nodes[8], nodes[9],
					nodes[10], nodes[11], nodes[12] });
		} else {
			return null;
		}
	}
	
	/**
	 * just to judge node with three sub nodes
	 * @param viewIndex
	 * @return
	 */
	public boolean isFullChildren(int viewIndex) {
		int[] subNodesViewIndex = TreeLayoutDefinition.findSubNodes(viewIndex);
		if(subNodesViewIndex == null || subNodesViewIndex.length == 0) {
			return false;
		}
		else
		{
			int max = subNodesViewIndex[2];
			return (max < count());
		}
	}
	
	
	/**
	 * just return three nodes under this node by viewIndex
	 * @param viewIndex
	 * @return
	 */
	public List<TreeNodeDto> getChildren(int viewIndex) {
		int[] subNodesViewIndex = TreeLayoutDefinition.findSubNodes(viewIndex);
		if(subNodesViewIndex == null || subNodesViewIndex.length == 0) {
			return null;
		}
		
		List<TreeNodeDto> subNodes = new ArrayList<TreeNodeDto>();
		for(TreeNodeDto dto : nodes) {
			for(int i=0; i<subNodesViewIndex.length; i++){
				if(dto.getViewIndex() == subNodesViewIndex[i]) {
					subNodes.add(dto);
				}
				
			}
		}
		return subNodes;
	}

	public List<TreeNodeDto> getLevel3() {
		if (nodes.length > 38) {
			return Arrays.asList(new TreeNodeDto[] { nodes[13], nodes[14], nodes[15], nodes[16], nodes[17], nodes[18],
					nodes[19], nodes[20], nodes[21], nodes[22], nodes[23], nodes[24], nodes[25], nodes[26], nodes[27],
					nodes[28], nodes[29], nodes[30], nodes[31], nodes[32], nodes[33], nodes[34], nodes[35], nodes[36],
					nodes[37], nodes[38] });
		} else {
			return null;
		}

	}

	public int count() {
		return nodes.length;
	}

	public int getEmptyCount() {
		return TreeLayoutDefinition.TREE_SIZE - nodes.length;
	}

	public boolean isTreeFull() {
		return (nodes.length == 39);
	}

}
